from __future__ import division, print_function, unicode_literals
import random
from color_type import ColorType

from tile_model import TileModel


class Pos():
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __str__(self):
        return '(%s, %s)' % (self.x, self.y)

    def __add__(self, other):
        return Pos(self.x + other.x, self.y + other.y)


def _turn_pos(p):
    if str(p) == '(-2, -2)':
        return Pos(-2, 1)
    if str(p) == '(-1, -2)':
        return Pos(-2, 0)
    if str(p) == '(0, -2)':
        return Pos(-2, -1)
    if str(p) == '(1, -2)':
        return Pos(-2, -2)
    if str(p) == '(-2, -1)':
        return Pos(-1, 1)
    if str(p) == '(-1, -1)':
        return Pos(-1, 0)
    if str(p) == '(0, -1)':
        return Pos(-1, -1)
    if str(p) == '(1, -1)':
        return Pos(-1, -2)
    if str(p) == '(-2, 0)':
        return Pos(0, 1)
    if str(p) == '(-1, 0)':
        return Pos(0, 0)
    if str(p) == '(0, 0)':
        return Pos(0, -1)
    if str(p) == '(1, 0)':
        return Pos(0, -2)
    if str(p) == '(-2, 1)':
        return Pos(1, 1)
    if str(p) == '(-1, 1)':
        return Pos(1, 0)
    if str(p) == '(0, 1)':
        return Pos(1, -1)
    if str(p) == '(1, 1)':
        return Pos(1, -2)


class Block(object):
    """
                    y:
    [00 01|02 03] -2
    [04 05|06 07] -1
    ------O------
    [08 09|10 11] 0
    [12 13|14 15] 1
    x:-2 -1  0  1
    """
    INDEX_POS_MAP = [
        Pos(-2, -2), Pos(-1, -2), Pos(0, -2), Pos(1, -2),
        Pos(-2, -1), Pos(-1, -1), Pos(0, -1), Pos(1, -1),
        Pos(-2, 0), Pos(-1, 0), Pos(0, 0), Pos(1, 0),
        Pos(-2, 1), Pos(-1, 1), Pos(0, 1), Pos(1, 1)
    ]
    """
    [00 01 02 03]
    [04 ** ** 07]
    [08 ** ** 11] --> 5 6 9 10
    [12 13 14 15]

    [00 01 02 03]
    [04 ** 06 07]
    [** ** ** 11] --> 5 8 9 10
    [12 13 14 15]
    """
    BLOCK_TYPE_DICTIONARY = {
        "2": [5, 6, 9, 10],  # 2*2
        "T": [5, 8, 9, 10],  # T
        "LL": [1, 5, 9, 10],  # LL
        "LR": [2, 6, 9, 10],  # LR
        "1": [1, 5, 9, 13],  # 1*4
        "ZL": [5, 6, 10, 11],  # ZL
        "ZR": [6, 7, 9, 10],  # ZR
    }
    BLOCK_TYPE = [
        [5, 6, 9, 10],  # 2*2
        [5, 8, 9, 10],  # T
        [1, 5, 9, 10],  # LL
        [2, 6, 9, 10],  # LR
        [1, 5, 9, 13],  # 1*4
        [5, 6, 10, 11],  # ZL
        [6, 7, 9, 10],  # ZR
    ]

    @staticmethod
    def random_block():
        return Block(random.randint(0, len(Block.BLOCK_TYPE) - 1))

    def __init__(self, type=0, x=0, y=0):
        self._x = x
        self._y = y
        self._type = type
        self._color = ColorType.ALL[random.randint(0, len(ColorType.ALL) - 1)]

        self._tile_pos = []
        for index in Block.BLOCK_TYPE[type]:
            self._tile_pos.append(Block.INDEX_POS_MAP[index])

    def set_pos(self, x, y):
        self._x = x
        self._y = y

    def get_tile_model(self):
        tile_model = []
        origin = Pos(self._x, self._y)
        for pos in self._tile_pos:
            new_pos = origin + pos
            tile_model.append(TileModel(new_pos.x, new_pos.y, self._color))
        return tile_model

    def rotate(self):
        result = []
        for pos in self._tile_pos:
            result.append(_turn_pos(pos))
        self._tile_pos = result

    def move_left(self):
        self.set_pos(self._x - 1, self._y)

    def move_right(self):
        self.set_pos(self._x + 1, self._y)

    def move_down(self):
        self.set_pos(self._x,  self._y - 1)
